0 ' =================================================================
1 ' NUMAZE by Ken Pettit, 2018
2 '
3 ' NOTE: With all the comments, this file is too large to load 
4 '       to the Model 200 and then convert to BASIC.  It was 
5 '       tested by deleteing all comment lines and then loading /
6 '       running using VirtualT.
9 ' =================================================================
20 ' Clear the screen and define all variables as INT (2 byte). We will change K-Q to STRing later
21 CLS:DEFINTA-Z
22 ' Dimension an array to hold the play field numbers
23 DIMA(15,34)
24 ' Initialize the T200 random number generator using a background ISR count
25 POKE-2259,PEEK(-3553)
26 ' Loop for 16 LCD lines and 31 LCD columns, skiping every other column. 
27 FORY=0TO15:FORX=0TO30STEP2
28 ' Generate random numbers for the playing field
29 A(Y,X)=RND(1)*7
30 ' Complete the loops
31 NEXT:NEXT
32 ' Initialize keystroke to UP/DOWN direction lookup table
33 B(1)=-1:B(2)=1
90 ' =================================================================
91 ' This section creates one path through the maze so it is solveable
97 ' Original line number 1.
98 ' =================================================================
99 ' Pick a random starting Row
100 R=RND(1)*15
110 ' Loop for each column, skiping every other one (those have lines)
120 FORI=0TO30STEP2
124 ' Get the number at the current row,col.  This is the (H)eight offset to the next step through the maze
125 H=A(R,I)
128 ' Calculate a new random number to place at the next column to the right.  The AND/OR/XOR logic
129 ' is generating a number whose LSB is the opposite from the current row/col (i.e. even->odd, odd->even)
130 V=(RND(1)*7AND254)OR(HAND1XOR1)
134 ' Choose a random direction (1 or 2)
135 D=RND(1)*2+1
139 ' Convert direction (1 or 2) to -1 or +1 using direction lookup table
140 D=B(D)
144 ' Add one to Height offset since we store it in the "A" table as zero-based
145 H=H+1
148 ' Calculate the propo(S)ed row where we should insert the new ODD/EVEN random number based on
149 ' the generated random direction.  We may need to swap UP/DOWN if this causes S to go out of bounds.
150 S=R+D*H
154 ' Call routine to test if S is out of bounds and update the Array
155 GOSUB700
159 ' Complete the loop to advance to the next column through the maze
160 NEXT
195 ' =================================================================
196 ' This section draws the playing field.
197 ' Original line number 2.
198 ' =================================================================
199 ' Loop for 16 lines, 31 columns
200 FORY=0TO15:FORX=0TO30STEP2
209 ' Print the next column, leaving 1 black column at left for cursor to choose entry location.
210 PRINT@Y*40+X+1,""CHR$(A(Y,X)+49);
214 ' Complete the loop and terminate the right-side of the field with a horizontal line
215 NEXT:PRINT"";
219 ' Complete the loop to advance to the next LCD row
220 NEXT
223 ' Define variables K through Q as STRing type.  This saves us
224 ' bytes since we can write 'K' instead of 'K$', P vs P$, etc.
225 DEFSTRK-Q
229 ' Initialize the (P)rint chracter as our cursor, '>'
230 P=">"
234 ' Set the starting (R)ow and (C)olumn
235 R=8:C=0
237 ' Initialize one of the Q string lookup table entries for drawing line graphic corners 
238 ' through the maze.  The other Q table entry is initialzed (repeately) in the print subroutine
239 ' simply becuase that was the only space availble while keeping the line length limited to 120.
240 Q(0)=""
290 ' =================================================================
291 ' This section is the main loop for reading keyboard input
292 ' Note that this code is slightly different when split into 
293 ' multiple lines because the ELSE portion of IF only works when on
294 ' the same line number.  When split up, the ELSE can't be used.
297 ' =================================================================
298 ' First thing to do is print whatever our is the current print character. 
299 ' We are "overprinting" every time through the loop, but we have to fit in 10 lines :)
300 GOSUB600
304 ' Get keyboard input, non-blocking (i.e. don't require ENTER)
305 K=INKEY$
309 ' Test if a key was pressed and return to main loop if not
310 IFK=""THEN300 ' IMPLIED ELSE HERE...on to next line
314 ' Test for quit key (q)
315 IFK="q"THENCLS:END ' IMPLIED ELSE HERE...on to next line
319 ' Test if we are in "Entry point select mode" (i.e. cursor is on column 0)
320 IFC=0THEN800 ' Go process entry logic plus IMPLIED ELSE
324 ' Test for Retry key and jump back to draw screen code
325 IFK="r"THEN200 ' IMPLIED ELSE
329 ' Lookup the keystrok in a string table and give the index 0-2 (since MOD 3)
330 D=INSTR("du jk",K)MOD3
339 ' Test for keystroke other than 'dujk' and return to main loop
340 IFD=0THEN300 ' NO implied else
390 ' =================================================================
391 ' This section determines if the selected move (UP/DOWN) is legal
392 ' or not (i.e. alternating ODD/EVEN and in bounds).
393 ' This is original line number 4.
398 ' =================================================================
399 ' First get the (H)eigth of movement at current row/col
400 H=A(R,C-1)+1
404 ' Convert keystroke direction to +1 / -1 via lookup table in B
405 D=B(D)
409 ' Calculated propo(S)ed row to jump to (via keystroke)
410 S=R-H*D
414 ' Test if proposed new row number is out of bounds and jump to main loop if it is
415 IFS<0ORS>15THEN300 ' IMPLIED ELSE
419 ' Get the random number in the NEXT column at the proposed row so we can test EVEN/ODD
420 V=A(S,C+1)
429 ' Test if current position number and new position number follow EVEN to ODD or ODD to EVEN rule
430 IF((VXORH)AND1)=1THENBEEP:GOTO300 ' IMPLIED ELSE and report error / jump to main loop if invalid
438 ' Move is valid!  Draw a line graphic '-' at the current row/col.  The cursor is sitting in the
439 ' vertical line region between the numbers and we must "connect the dots" to draw a solid line.
440 P="":GOSUB600
449 ' Advance to next column
450 C=C+1
447 ' Original line number 5.  Choose/print line graphic character for corner UP or DOWN from lookup
448 ' table in Q based on the move direction.  D is +1 / -1 now so we must add 1.  The table
449 ' has been initialized with Q(0) = DOWN graphic, Q(2) = UP graphic and Q(1) not used.
497 ' ==========================
498 ' Original line number 5.
499 ' ==========================
500 P=Q(D+1):GOSUB600
509 ' Change the (P)rint character to line graphic '|' to draw vertical path through the maze.
510 P=""
519 ' Loop through each row to the destination row to draw the path
520 FORI=1TOH
529 ' Update Row by +1/-1 based on move direction and print the next '|' character there.
530 R=R-D:GOSUB600
539 ' Loop for all rows that need to be printed
540 NEXT
549 ' Choose / print corner graphic at the end of the line from P table based on move direction (like Q above).
550 P=P(D+1):GOSUB600
559 ' Advance to next column (within vertical maze line inbetween the numbers).
560 C=C+1
569 ' Change the (P)rint character back to our cursor and return to main loop.  It will print the '>' for us.
570 P=">":GOTO300
590 ' =================================================================
591 ' This section prints the current (P)rint character and tests for
592 ' Win condition (based on current column number).  It also does
593 ' some (repeated) initialization of our lookup table values
594 ' simply because there was no other space in the PUR-120 10-Line
595 ' program to fit the initialization.
597 ' Original line number 6.
598 ' =================================================================
599 ' Initalize Corner graphic lookup table
600 P(0)=""
610 P(2)=""
620 Q(2)=""
629 ' Initialzie diretion UP/DOWN table for 'jk' keys
630 B(3)=-1
640 B(4)=1
649 ' Finally print the (P)rint character at the current Row/Col
650 PRINT@R*40+C,P;
659 ' Test for Win.  This is when Col advances to col 34
660 IFC<33THENRETURN ' IMPLIED ELSE
670 PRINT@435,"Win!"
680 END
690 ' =================================================================
691 ' This section is part of the "create path through maze" code. It
692 ' validates the randomly picked direction is not out of bounds and
693 ' reverses the direction if it is.  Then it updates the play field
694 ' (A)rray at the chosen destination with the randomly generated 
695 ' (V)alue which follows the ODD/EVEN rule.
696 ' Original line number 7.
697 ' =================================================================
698 ' Save the current Row through of path for debug.  Also, if we decide to add 'h'int mode
699 ' later as part of a non-10-Liner, this becomes our history of the created path.
700 A(0,I+1)=R
703 ' Test if the randomly chosen propo(S)ed row is out of bounds and reverse UP/DOWN if it is.
705 IFS<0ORS>15THENS=R-D*HELSE730
709 ' Save new ODD/EVEN (V)alue generated at the destination row in the next column
710 A(S,I+2)=V
714 ' Change our current (R)ow variable so it is now the new propo(S)ed row and return
715 R=S
720 RETURN ' IMPLIED ELSE from test for out of bounds
729 ' The propo(S)ed new row not out of bounds.  Save EVEN/ODD (V)alue in (A)rray
730 A(S,I+2)=V
739 ' Change current (R)ow to propo(S)ed row.
740 R=S
748 ' Test if this is the (F)irst pass through this routine and if it is, call the routine
749 ' at 900 to print the NUMAZE and key helper text.
750 IFF=0THENGOSUB900:F=1:RETURN ' IMPLIED ELSE
760 RETURN
790 ' =================================================================
791 ' This section handles UP/DOWN and 'e'nter keys during the "choose
792 ' entry location" phase (i.e. when (C)olumn = 0).
797 ' Original line number 8.
798 ' =================================================================
799 ' Change (P)rint character to space to erase cursor at current location.
800 P=" "
809 ' Call routine to print it.
810 GOSUB600
819 ' Change (P)rint character back to our cursor
820 P=">"
829 ' Test for 'e'nter key and advance column into the maze if detected
830 IFK="e"THENC=C+1
839 ' Jump back to main loop, we are in. It will print our cursor for us.
840 GOTO300 ' IMPLIED ELSE
848 ' Lookup keystroke, returning index 0-4 and then use it to lookup 
849 ' move direction +1 / -1 in our lookup ta(B)le
850 D=B(INSTR("jkdu",K))
859 ' Limit row to 0-15, wrapping 16 back to zero
860 R=(R-D)MOD16
869 ' Test for row wrapping from zero to -1 and wrap to 15 instead
870 IFR<0THENR=15:GOTO300 ' IMPLIED ELSE
880 GOTO300
890 ' =================================================================
891 ' This section prints the NUMAZE and key helper text.
892 ' The routine is called during the "create path through maze"
893 ' code from the subroutine starting at 800.
897 ' Original line number 9.
898 ' =================================================================
900 PRINT@34,"NUMAZE"
910 PRINT@114,"uk: UP"
920 PRINT@154,"dj:DWN"
930 PRINT@194,"e:ENTR"
940 PRINT@234,"r:RTRY"
950 PRINT@274,"q"
960 RETURN

